# -*- coding: UTF-8 -*-
from matplotlib import pyplot as plt
import json


#画容量-电压图
def draw_C_V_plt(samples,
                 NumberFilter,
                 Layout_Parameters,
                 width,height,
                 xlim=False,ylim=False
                 ):

    for sample in samples:
        plt.figure(figsize=(width, height))
        plt.axes([0.15,0.17,0.8,0.7])
        ax = plt.gca()
        # 从json读取参数并改变图标样式
        plt.rcParams['font.sans-serif'] = [Layout_Parameters['font']]
        ax.spines['bottom'].set_linewidth(Layout_Parameters['axis_thikness'])
        ax.spines['left'].set_linewidth(Layout_Parameters['axis_thikness'])
        ax.spines['right'].set_linewidth(Layout_Parameters['axis_thikness'])
        ax.spines['top'].set_linewidth(Layout_Parameters['axis_thikness'])



        plt.title(sample.name.get())
        plt.ylabel(r'Voltage / V', fontsize=Layout_Parameters['label_font_size'])
        plt.xlabel(r'Specific Capacity / mAh·g$^{-1}$', fontsize=Layout_Parameters['label_font_size'])
        plt.xticks(fontsize=Layout_Parameters['tick_font_size'])
        plt.yticks(fontsize=Layout_Parameters['tick_font_size'])
        plots_discharge = []
        plots_charge = []
        if xlim:
            plt.xlim(xlim)
        if ylim:
            plt.ylim(ylim)
        Sample_plotting_count = 0
        if sample.bias:
            NumberFilter = [nf+sample.bias for nf in NumberFilter]

        DischargeCOLs , ChargeCOLs = read_1df_for_C_V(sample.RawDF,NumberFilter)
        for x in NumberFilter:
            disCap = DischargeCOLs.loc[DischargeCOLs[r'循环序号'] == x][r'比容量/mAh/g'].values.T
            disVol = DischargeCOLs.loc[DischargeCOLs[r'循环序号'] == x][r'电压/V'].values.T
            chrCap = ChargeCOLs.loc[ChargeCOLs[r'循环序号'] == x][r'比容量/mAh/g'].values.T
            chrVol = ChargeCOLs.loc[ChargeCOLs[r'循环序号'] == x][r'电压/V'].values.T
            plots_discharge.append(plt.plot(disCap, disVol ,
                                            color=Layout_Parameters['C_Vcolors'][Sample_plotting_count],
                                            label=ordinal(str(x-sample.bias)),
                                            linewidth=Layout_Parameters['line_thikness'],
                                            linestyle=Layout_Parameters['line_styles'][Sample_plotting_count]))
            plots_charge.append(plt.plot(chrCap, chrVol,
                                         color=Layout_Parameters['C_Vcolors'][Sample_plotting_count],
                                         label=ordinal(str(x-sample.bias)),
                                         linewidth=Layout_Parameters['line_thikness'],
                                         linestyle=Layout_Parameters['line_styles'][Sample_plotting_count]))
            Sample_plotting_count += 1
        Sample_plotting_count = 0
        raw_handles, raw_labels = ax.get_legend_handles_labels()
        handles = []
        labels = []
        for x in range(len(NumberFilter)):
            handles.append(raw_handles[2*x])
            labels.append(raw_labels[2*x])
        plt.legend(handles,labels,frameon=False,fontsize=Layout_Parameters['legend_font_size'])
        plt.show()
#从单一df读取充放电数组，返回一组电池的放电，充电df
def read_1df_for_C_V(RawDataFrame,NumFilter=False):
    AllDischargeCOL = RawDataFrame.loc[RawDataFrame[r'工步状态'].str.contains(r'RateD|CCD')]
    AllChargeCOL = RawDataFrame.loc[RawDataFrame[r'工步状态'].str.contains(r'RateC|CCC')]
    if NumFilter:
        AllDischargeCOL = AllDischargeCOL.loc[AllDischargeCOL[r'循环序号'].isin(NumFilter)]
        AllChargeCOL = AllChargeCOL.loc[AllChargeCOL[r'循环序号'].isin(NumFilter)]
    return AllDischargeCOL , AllChargeCOL
#----------------------------------------------------------------------------------------------------------------------------------------
#绘画对称电池用 预读取 获取横，纵坐标最大值
def PreReadForLSC(RawDataFrames):
    TotalTimes = []
    for LSC_data in RawDataFrames:
        TotalTimes.append(LSC_data[r'测试时间/Sec'].max())
    maxTotalVols = []
    for LSC_data in RawDataFrames:
        maxTotalVols.append(LSC_data[r'电压/V'].max())
    minTotalVols = []
    for LSC_data in RawDataFrames:
        minTotalVols.append(LSC_data[r'电压/V'].min())

    absmaxTotalVol = max(max(maxTotalVols) , min(minTotalVols))
    return max(TotalTimes) , absmaxTotalVol
#从单一df读取时间-电压曲线
def read_1df_for_LSC(RawDataFrame):
    LSCcurbedf = RawDataFrame[['测试时间/Sec','电压/V']]
    return LSCcurbedf
#对称电池的时间-电压曲线
def draw_LSC_plt(samples,
                 Layout_Parameters,
                 width,
                 height,
                 xlim=False,
                 ylimmax=False,
                 ylimmin=False
                 ):
    plots = []
    plt.figure(figsize=((width,height)))
    plt.axes([0.15, 0.17, 0.8, 0.7])
    plt.ylabel(r'Voltage / V',fontsize=Layout_Parameters['label_font_size'])
    plt.xlabel(r'Time / h',fontsize=Layout_Parameters['label_font_size'])
    plt.xticks(fontsize=Layout_Parameters['tick_font_size'])
    plt.yticks(fontsize=Layout_Parameters['tick_font_size'])

    plt.xlim(0,xlim)
    plt.ylim(ylimmin,ylimmax)
    ax = plt.gca()
    #从json读取参数并改变图标样式
    plt.rcParams['font.sans-serif'] = [Layout_Parameters['font']]
    ax.spines['bottom'].set_linewidth(Layout_Parameters['axis_thikness'])
    ax.spines['left'].set_linewidth(Layout_Parameters['axis_thikness'])
    ax.spines['right'].set_linewidth(Layout_Parameters['axis_thikness'])
    ax.spines['top'].set_linewidth(Layout_Parameters['axis_thikness'])

    Sample_plotting_count = 0
    for sample in samples:
        df = read_1df_for_LSC(sample.RawDF)
        Xtime = df['测试时间/Sec'].values.T
        Yvoltage = df['电压/V'].values.T
        plots.append(plt.plot(Xtime/3600,Yvoltage,
                              label=sample.name.get(),
                              color=sample.Line_Color,
                              linewidth=Layout_Parameters['line_thikness'],
                              linestyle=sample.Line_Style
                              ))
        Sample_plotting_count += 1


    handles, labels = ax.get_legend_handles_labels()
    plt.legend(handles, labels, frameon=False,fontsize=Layout_Parameters['legend_font_size'])
    plt.show()
#-------------------------------------------------------------------------------------------------------------------------
#循环圈数-比容量-效率 1.读取循环圈数最大值
def PreReadForCNP(RawDataFrames):
    Max_CycleNumbers = []
    for df in RawDataFrames:
        Max_CycleNumbers.append(df['循环序号'].max())
    Max_Specific_Capacities = []
    for df2 in RawDataFrames:
        Max_Specific_Capacities.append(df2['放电比容量/mAh/g'].max())
        Max_Specific_Capacities.append(df2['充电比容量/mAh/g'].max())
    return max(Max_CycleNumbers) , max(Max_Specific_Capacities)
#偏移数据
def df_bias(RawDataFrame,New_Start):
    if New_Start == 0:
        return RawDataFrame
    else:
        new_df = RawDataFrame.iloc[(New_Start-1):]
        new_df['循环序号'] = new_df['循环序号'] - New_Start +1
        return new_df
#读取某一df的 循环圈数-比容量-效率
def read_1df_for_CNP(RawDataFrame):
    CNPdf = RawDataFrame[['循环序号','放电比容量/mAh/g','充电比容量/mAh/g',r'效率/%']]
    return CNPdf
#全电池的循环圈数-比容量-效率曲线
def draw_CNP_plt(samples,
                 Layout_Parameters,
                 width=8,
                 height=4,
                 xlim_max=False,
                 subymax=False,
                 ylimmax=False,
                 ylimmin=False,
                 ):
    fig,sub_plot = plt.subplots(figsize=((width, height)))
    sub_plot1 = sub_plot.twinx()
    sub_plot.set_xlabel(r'Cycle Number', fontsize=Layout_Parameters['label_font_size'])
    sub_plot.set_ylabel(r'Specific Capacity / mAh·g$^{-1}$', fontsize=Layout_Parameters['label_font_size'])
    sub_plot.tick_params(labelsize=Layout_Parameters['tick_font_size'])
    sub_plot1.tick_params(labelsize=Layout_Parameters['tick_font_size'])
    sub_plot1.set_ylabel(r'Coulomb Efficiency / %', fontsize=Layout_Parameters['label_font_size'])

    plt.xlim(0, xlim_max)
    if ylimmin or ylimmin==0:
        if ylimmax:
            print(123124125136)
            sub_plot.set_ylim(ylimmin, ylimmax)
    sub_plot1.set_ylim(0,int(subymax))



    # 从json读取参数并改变图表样式
    plt.rcParams['font.sans-serif'] = [Layout_Parameters['font']]
    sub_plot.spines['bottom'].set_linewidth(Layout_Parameters['axis_thikness'])
    sub_plot.spines['left'].set_linewidth(Layout_Parameters['axis_thikness'])
    sub_plot.spines['right'].set_linewidth(Layout_Parameters['axis_thikness'])
    sub_plot.spines['top'].set_linewidth(Layout_Parameters['axis_thikness'])


    Sample_plotting_count = 0
    for sample in samples:
        if sample.bias:
            RawDataFrame = df_bias(sample.RawDF,sample.bias)
        else:
            RawDataFrame = sample.RawDF

        df = read_1df_for_CNP(RawDataFrame)

        X_CycleNumber = df['循环序号'].values.T
        Y_Specific_Capacity = df['放电比容量/mAh/g'].values.T
        Y_CE = df[r'效率/%'].values.T
        sub_plot.plot(X_CycleNumber, Y_Specific_Capacity, label=sample.name.get(),
                              color=sample.Line_Color,
                              linewidth=Layout_Parameters['line_thikness'],
                              marker=sample.Marker_Style,
                              linestyle=sample.Line_Style
                              )
        sub_plot1.plot(X_CycleNumber, Y_CE, label=sample.name.get(),
                              color=sample.Line_Color,
                              linewidth=Layout_Parameters['line_thikness'],
                              marker=sample.Marker_Style,
                              markerfacecolor='white',
                              linestyle=sample.Line_Style
                              )
        Sample_plotting_count += 1

    handles, labels = sub_plot.get_legend_handles_labels()
    plt.legend(handles, labels, frameon=False, fontsize=Layout_Parameters['legend_font_size'])
    plt.show()
    return




#数字改序数词
def ordinal(n):
    if int(n) == 11 or int(n) ==12 or int(n) ==13:
        return n+'th'
    if n[-1] == '1':
        return n+'st'
    if n[-1] == '2':
        return n+'nd'
    if n[-1] == '3':
        return n+'rd'
    return n+'th'


def readParameters(jsondir='layout.json'):
    with open(jsondir, 'r') as jsonfile:
        Layout_Parameters_contents = jsonfile.read()
        Raw_Layout_Parameters = json.loads(Layout_Parameters_contents)
        Layout_Parameters = JsonToParameter(Raw_Layout_Parameters)
    return Layout_Parameters
def JsonToParameter(input):
    #判断读取的json是否数字
    def is_number(s):
        try:  # 如果能运行float(s)语句，返回True（字符串s是浮点数）
            float(s)
            return True
        except ValueError:  # ValueError为Python的一种标准异常，表示"传入无效的参数"
            pass  # 如果引发了ValueError这种异常，不做任何事情（pass：不做任何事情，一般用做占位语句）
        try:
            import unicodedata  # 处理ASCii码的包
            unicodedata.numeric(s)  # 把一个表示数字的字符串转换为浮点数返回的函数
            return True
        except (TypeError, ValueError):
            pass
        return False
    # 判断读取的json是否为list
    def is_list(l):
        if r',' in l:
            return True
        else:
            return False
    #"数字"转数字 "列表"转列表
    for key in input.keys():
        print(input[key])
        if is_number(input[key]):
            input[key] = float(input[key])
        elif is_list(input[key]):
            input[key] = input[key].split(',')

    return input
if __name__ == '__main__':
    # # 测试容量-电压 曲线
    # colorlist = [
    #     'aliceblue',
    #     'violet',
    #     'red',
    #     'olive',
    #     'olive'
    # ]
    # All_Raw_data = []
    # All_Raw_data.append(pd.read_csv('test.csv',encoding="gbk"))
    # print(All_Raw_data)
    # draw_C_V_plt(All_Raw_data,[2,5,10],colorlist)

    # #测试 对称电池作图
    # root = tk.Tk()
    # sam_test = cl.Sample("test.csv",0,root)
    # cl.readParameters('layout.json')
    # Layout_Parameters = readParameters('layout.json')
    # draw_C_V_plt(sam_test,
    #              NumberFilter=[5,10,20],
    #              Layout_Parameters=Layout_Parameters,
    #              width=8, height=4,
    #              xlim=False, ylim=False
    #              )
    pass

